package site.jlopen.controller.api;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import site.jlopen.assets.config.ThreadAuthUser;
import site.jlopen.domain.node.event.KusciaNodeEvent;
import site.jlopen.entity.BaseResponse;
import site.jlopen.entity.KusciaApiInfo;
import site.jlopen.kuscia.cons.BaseCons;
import site.jlopen.kuscia.cons.DomainConstants;
import site.jlopen.kuscia.model.NodeVo;
import site.jlopen.kuscia.service.node.AbstractNodeManager;
import site.jlopen.mapper.node.KusciaNodeMapper;
import site.jlopen.secret.model.node.SecretNodeCreateReq;
import site.jlopen.secret.model.node.SecretNodeInfoResp;
import site.jlopen.utils.file.FileUtil;
import site.jlopen.utils.id.IdUtils;

@RestController
@RequestMapping(value="/api/node")
public class ApiNodeController {
	private final Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private KusciaNodeMapper nodeMapper;
	@Autowired
    private AbstractNodeManager nodeManager;
	@Value("${file.cert.dir}")
	private String certDir;
	
	@PostMapping(value = "/create" )
	public BaseResponse<SecretNodeInfoResp> create(@Validated  @RequestBody SecretNodeCreateReq req) {
		logger.info("节点创建接口调用");
		if(null == req.getCode()) {
			return new BaseResponse<SecretNodeInfoResp>().error("该节点ID不能为空");
		}
		if(!req.getProtocol().equals(BaseCons.KUSCIA_PROTOCOL) && 
			(null == req.getToken() || null == req.getCaFile() || null == req.getCertFile() || null == req.getKeyFile())) {
			return new BaseResponse<SecretNodeInfoResp>().error("非notls通讯模式请提交证书数据");
		}
		KusciaNodeEvent event = nodeMapper.selectByInfo(new KusciaNodeEvent().setNodeUserId(ThreadAuthUser.id()).setNodeCode(req.getCode()));
		if(null != event) {
			return new BaseResponse<SecretNodeInfoResp>().error("该节点"+req.getCode()+"已存在");
		}
		String parentPath   = certDir    + File.separator  + req.getCode() + File.separator + String.valueOf(IdUtils.SnowFlakeId());
		String caFileDir    = parentPath + File.separator + "ca.crt", 
				certFileDir = parentPath + File.separator + "kusciaapi-server.crt", 
				keyFileDir  = parentPath + File.separator + "kusciaapi-server.key", 
				tokenDir    = parentPath + File.separator + "token";
		if(!req.getProtocol().equals(BaseCons.KUSCIA_PROTOCOL)) {
			boolean tokenfos = FileUtil.byte2File(req.getToken(), parentPath, "token");
			if(tokenfos == false) {
				return new BaseResponse<SecretNodeInfoResp>().error("创建token文件失败");
			}
			boolean cafos = FileUtil.byte2File(req.getCaFile(), parentPath, "ca.crt");
			if(cafos == false) {
				return new BaseResponse<SecretNodeInfoResp>().error("创建ca.crt文件失败");
			}
			boolean serverCrtfos = FileUtil.byte2File(req.getCertFile(), parentPath, "kusciaapi-server.crt");
			if(serverCrtfos == false) {
				return new BaseResponse<SecretNodeInfoResp>().error("创建server.crt文件失败");
			}
			boolean serverKeyfos = FileUtil.byte2File(req.getKeyFile(), parentPath, "kusciaapi-server.key");
			if(serverKeyfos == false) {
				return new BaseResponse<SecretNodeInfoResp>().error("创建server.key文件失败");
			}
		}
		event = new KusciaNodeEvent();
		KusciaApiInfo apiInfo = new KusciaApiInfo(req.getProtocol(), req.getGrpc()).ext(tokenDir, certFileDir, keyFileDir, caFileDir);
		NodeVo nodeVo = nodeManager.queryNode(apiInfo, req.getCode());
		event.setNodeEnable(1);
		if(null != nodeVo) {
			event.setNodeEnable(nodeVo.getStatus().equals(DomainConstants.DomainEenableEnum.online.name())?0:1);
		}
		event.setNodeId(IdUtils.SnowFlakeId())
		.setNodeUserId(ThreadAuthUser.id())
		.setNodePlatform(req.getPlatform())
		.setNodeMode(req.getMode())
		.setNodeGroup(req.getGroup())
		.setNodeTitle(req.getTitle())
		.setNodeCode(req.getCode())
		.setNodeMaster(req.getMaster())
		.setNodeAuth(null)
		.setNodeGateway(req.getGateway())
		.setNodeGrpc(req.getGrpc())
		.setNodeHttp(req.getNet())
		.setNodeNet(req.getNet())
		.setNodeProtocol(req.getProtocol())
		.setNodeToken(tokenDir)
		.setNodeCa(caFileDir)
		.setNodeCert(certFileDir)
		.setNodeKey(keyFileDir)
		.setNodeCreate(new Date())
		;
		try {
			int row = nodeMapper.insertSelective(event);
			if(row > 0) {
				KusciaNodeEvent nevent = nodeMapper.selectByInfo(new KusciaNodeEvent().setNodeUserId(ThreadAuthUser.id()).setNodeCode(req.getCode()));
				return new BaseResponse<SecretNodeInfoResp>().success("创建成功").setData(nodeToResp(nevent));
			}
		} catch (Exception e) {
			logger.error("创建节点异常：{}", e);
			return new BaseResponse<SecretNodeInfoResp>().error("创建异常：" + e.getMessage());
		}
		return new BaseResponse<SecretNodeInfoResp>().error("创建失败");
	}
	
	@PostMapping(value = "/update" )
	public BaseResponse<SecretNodeInfoResp> update(@Validated  @RequestBody SecretNodeCreateReq req) {
		logger.info("修改节点接口调用");
		
		return new BaseResponse<SecretNodeInfoResp>().error("暂未支持");
	}
	
	@PostMapping(value = "/remove" )
	public BaseResponse<String> remove(String nodeCode) {
		logger.info("节点移除接口调用");
		KusciaNodeEvent event = nodeMapper.selectByInfo(new KusciaNodeEvent().setNodeUserId(ThreadAuthUser.id()).setNodeCode(nodeCode));
		if(null == event) {
			return new BaseResponse<String>().error("该节点"+nodeCode+"不存在");
		}
		int row = nodeMapper.deleteByKey(event.getNodeId());
		return new BaseResponse<String>().success("绑定记录删除成功").dbRes(row, "");
	}
	
	/*@PostMapping(value = "/valid" )
	public BaseResponse<String> valid() {
		logger.info("节点接口调用");
		return new BaseResponse<String>().success("成功");
	}*/
	
	@PostMapping(value = "/reStatus" )
	public BaseResponse<String> refresh(String nodeCode) {
		logger.info("节点状态刷新接口调用");
		KusciaNodeEvent event = nodeMapper.selectByInfo(new KusciaNodeEvent().setNodeUserId(ThreadAuthUser.id()).setNodeCode(nodeCode));
		if(null == event) {
			return new BaseResponse<String>().error("该节点"+nodeCode+"不存在");
		}
		KusciaApiInfo apiInfo = new KusciaApiInfo(event.getNodeProtocol(), event.getNodeGrpc()).ext(event.getNodeToken(), event.getNodeCert(), event.getNodeKey(), event.getNodeCa());
		NodeVo nodeVo = nodeManager.queryNode(apiInfo, event.getNodeCode());
		if(null == nodeVo) {
			return new BaseResponse<String>().error("该节点"+nodeCode+"未部署");
		}
		event.setNodeEnable(nodeVo.getStatus().equals(DomainConstants.DomainEenableEnum.online.name())?0:1);
		nodeMapper.updateSelective(event);
		return new BaseResponse<String>().success("状态刷新成功");
	}
	
	@PostMapping(value = "/info" )
	public BaseResponse<SecretNodeInfoResp> info(String nodeCode) {
		logger.info("节点接口调用");
		KusciaNodeEvent event = nodeMapper.selectByInfo(new KusciaNodeEvent().setNodeUserId(ThreadAuthUser.id()).setNodeCode(nodeCode));
		if(null == event) {
			return new BaseResponse<SecretNodeInfoResp>().error("该节点信息不存在");
		}
		return new BaseResponse<SecretNodeInfoResp>().success("OK").setData(nodeToResp(event));
	}
	
	@PostMapping(value = "/list" )
	public BaseResponse<List<SecretNodeInfoResp>> list() {
		logger.info("节点列表接口调用");
		Map<String, Object> records = new HashMap<String, Object>();
		records.put("nodeUserId", ThreadAuthUser.id());
		List<KusciaNodeEvent> list = nodeMapper.selectAllNotPage(records);
		List<SecretNodeInfoResp> res = new ArrayList<SecretNodeInfoResp>();
		if(null != list && list.size() > 0) {
			for (KusciaNodeEvent event : list) {
				res.add(nodeToResp(event));
			}
		}
		return new BaseResponse<List<SecretNodeInfoResp>>().success("OK").setData(res);
	}
	
	private SecretNodeInfoResp nodeToResp(KusciaNodeEvent event) {
		SecretNodeInfoResp info = new SecretNodeInfoResp(
				event.getNodeId(), 
				event.getNodePlatform(), 
				event.getNodeMode(), 
				event.getNodeGroup(), 
				event.getNodeTitle(), 
				event.getNodeCode(), 
				event.getNodeMaster(), 
				event.getNodeNet(), 
				event.getNodeGrpc(), 
				event.getNodeProtocol(), 
				event.getNodeDeployToken(), 
				event.getNodeEnable(), 
				event.getNodeCreate()
				);
		return info;
	}
	
}